/*	--- 使用Annotation配置 --- 

使用【Spring的IoC容器】，实际上就是通过【类似XML这样的配置文件】，把我们自己的【Bean的依赖关系】描述出来，然后让【容器】来【创建并装配Bean】。

一旦【容器】初始化完毕，我们就直接从【容器】中获取【Bean】使用它们。

------------------------------

使用【XML配置】的优点是: 【所有的Bean】都能【一目了然地列出】，并通过【配置注入】能直观地看到【每个Bean的依赖】。

【它的缺点】是【写起来非常繁琐】，每增加【一个组件】，就必须把【新的Bean】配置到【XML】中。

------------------------------------

有没有【其他更简单的配置方式】呢？

有！我们可以使用【Annotation配置】，可以【完全不需要XML】，让【Spring】自动扫描【Bean】并【组装它们】。

我们把【上一节的示例】改造一下，先【删除XML配置文件】

然后，给【UserService】和【MailService】添加【几个注解】。

-----------------------------------------------------

首先，我们给【MailService】添加一个【@Component注解】： */
@Component
public class MailService {
	//...
}


/*
这个【@Component注解】就相当于定义了【一个Bean】，它有【一个可选的名称】，默认是【mailService，即小写开头的class名】。

然后，我们给【class UserService】添加【一个@Component注解】和【一个@Autowired注解】： */
@Component
public class UserService {
	@Autowired
	MailService mailService;

	//...
}


/*
【使用@Autowired】就相当于把【指定type的Bean】注入到【指定的Field字段】中。

和【XML配置】相比，【@Autowired】大幅简化了【注入】，因为它不但可以写在【set()方法】上，还可以直接写在【Field, 字段】上，甚至可以写在【构造方法】中： */
@Component
public class UserService {
	MailService mailService;

	public UserService(@Autowired MailService mailService) {
		this.mailService = mailService;
	}

	//...
}


/*
我们一般把【@Autowired】写在【字段】上，通常使用【package权限】的【字段】，便于测试。

-----------------------------------

最后，编写一个【AppConfig类】启动【容器】： */
@Configuration // <-- 表示这是一个AnnotationConfig,注释配置类
@ComponentScan // 组件扫描
public class AppConfig {
	public static void main(String[] args) {

		ApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class); // 通过AppConfig.class配置Bean
		UserService userService = context.getBean(UserService.class);
		User user = userService.login("bob@example.com", "password");

		System.out.println(user.getName());

	}
}


/*
除了【main()方法】外，【AppConfig】标注了【@Configuration】，表示【它】是【一个配置类】，

因为我们【创建ApplicationContext】时： */
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 以自己作为"注释配置class"


/*
使用的【实现类】是【AnnotationConfigApplicationContext】，必须传入【一个标注了@Configuration的class名】。


此外，【AppConfig】还标注了【@ComponentScan】

【@ComponentScan】告诉【容器】，自动搜索【当前class】所在的【路径package+路径子包】，把【所有【标注】为【@Component的Bean】自动创建出【Instance】来，并【根据@Autowired】进行【装配】。


【整个工程结构】如下：
--------------------------------------------------------
	spring-ioc-annoconfig
	├── pom.xml
	└── src
	    └── main
	        └── java
	            └── com
	                └── itranswarp
	                    └── learnjava
	                        ├── AppConfig.java
	                        └── service
	                            ├── MailService.java
	                            ├── User.java
	                            └── UserService.java

--------------------------------------------------------------


【使用Annotation】配合【自动扫描】能大幅简化【Spring的配置】，


我们【只需要保证】：
· 【每个Bean】被标注为【@Component】并正确使用【@Autowired注入】；
· 【配置类】被标注为【@Configuration 和 @ComponentScan】；
· 【所有Bean】均在【指定包 以及 子包内】。

使用【@ComponentScan】非常方便，但是，我们也要特别注意【包的层次结构】。

通常来说，启动【配置AppConfig】位于【自定义的顶层包】（例如com.itranswarp.learnjava），【其他Bean】按【类别】放入【子包】。




=================================================================


#	思考

如果我们想给【UserService】注入【HikariDataSource】，但是【这个类】位于【com.zaxxer.hikari包】中，并且【HikariDataSource】也不可能有【@Component注解】，如何告诉【IoC容器】创建并配置【HikariDataSource】？

或者换个说法，【如何创建并配置】一个【第三方Bean】？


=================================================================

#	练习

使用Annotation配置IoC容器 */


/*===============================================================

#	----- 使用Annotation の 小结 ----- 


1. 使用【Annotation】可以【大幅简化配置】，【每个Bean】通过【@Component和@Autowired】注入；

2. 必须合理设计【包的层次结构】，才能发挥【@ComponentScan】的威力。



*/





































